import type {
  IActionInfo,
  IAllowedRequest,
  IBatchAllowedResponse,
  ICollaborator,
  ICreateRequest,
  ICreateRequest_SelectRangeObject,
  IListPermPointRequest,
  IPermissionPoint,
  IPutCollaboratorsRequest,
  IUnitRoleKV,
  IUpdatePermPointRequest,
} from '@univerjs/protocol'
import { Injector } from '@univerjs/core'
import {
  createDefaultUser,
  generateRandomId,
  IAuthzIoService,
  Inject,
  IResourceManagerService,
  UserManagerService,
} from '@univerjs/core'
import { ObjectScope, UnitAction, UnitObject, UnitRole, UniverType } from '@univerjs/protocol'
// 替换原有的 isDevRole 函数实现
function isDevRole(userID: string, type: UnitRole): boolean {
  // 开发者角色判断逻辑：
  // 1. 如果用户ID为空，返回false
  if (!userID) return false

  // 2. 如果是Owner角色，直接返回true
  if (type === UnitRole.Owner) return true

  // 3. 可以根据实际业务需求扩展其他判断逻辑
  // 例如：检查用户ID是否在开发者名单中
  const devUserIds = ['admin123', 'dev456'] // 示例开发者用户ID列表
  return devUserIds.includes(userID)
}

class YourAuthzService implements IAuthzIoService {
  private _permissionMap: Map<
    string,
    ICreateRequest_SelectRangeObject & { objectType: UnitObject }
  > = new Map([])

  constructor(
    @Inject(IResourceManagerService) private _resourceManagerService: IResourceManagerService,
    @Inject(UserManagerService) private _userManagerService: UserManagerService,
  ) {
    this._initSnapshot()
    this._initDefaultUser()
  }

  private _initDefaultUser() {
    console.log('list', 'xxxxxx')
    const currentUser = this._userManagerService.getCurrentUser()
    const currentUserIsValid = currentUser && currentUser.userID

    if (!currentUserIsValid) {
      this._userManagerService.setCurrentUser(createDefaultUser(UnitRole.Owner))
    }
  }

  private _getRole(type: UnitRole) {
    const user = this._userManagerService.getCurrentUser()
    if (!user) {
      return false
    }
    return isDevRole(user.userID, type)
  }

  private _initSnapshot() {
    console.log('_initSnapshot')
    this._resourceManagerService.registerPluginResource({
      toJson: (_unitId: string) => {
        const obj = [...this._permissionMap.keys()].reduce(
          (r, k) => {
            const v = this._permissionMap.get(k)
            r[k] = v!
            return r
          },
          {} as Record<string, ICreateRequest_SelectRangeObject & { objectType: UnitObject }>,
        )
        return JSON.stringify(obj)
      },
      parseJson: (json: string) => {
        return JSON.parse(json)
      },
      pluginName: 'SHEET_AuthzIoMockService_PLUGIN',
      businesses: [UniverType.UNIVER_SHEET, UniverType.UNIVER_DOC, UniverType.UNIVER_SLIDE],
      onLoad: (_unitId, resource) => {
        console.log('_onLoad', resource)
        for (const key in resource) {
          this._permissionMap.set(key, resource[key])
        }
      },
      onUnLoad: () => {
        this._permissionMap.clear()
      },
    })
  }

  async create(config: ICreateRequest): Promise<string> {
    const permissionId = generateRandomId(8)
    if (config.objectType === UnitObject.SelectRange && config.selectRangeObject) {
      this._permissionMap.set(permissionId, {
        ...config.selectRangeObject,
        objectType: config.objectType,
      })
    }
    return permissionId
  }

  async batchAllowed(config: IAllowedRequest[]): Promise<IBatchAllowedResponse['objectActions']> {
    const selectionRangeConfig = config.filter((c) => c.objectType === UnitObject.SelectRange)
    if (selectionRangeConfig.length) {
      const currentUser = this._userManagerService.getCurrentUser()
      const res = [] as IBatchAllowedResponse['objectActions']
      selectionRangeConfig.forEach((c) => {
        res.push({
          unitID: c.unitID,
          objectID: c.objectID,
          actions: c.actions.map((action) => {
            if (isDevRole(currentUser.userID, UnitRole.Owner)) {
              return { action, allowed: true }
            }
            return { action, allowed: false }
          }),
        })
      })
      return res
    }
    return Promise.resolve([])
  }

  async list(config: IListPermPointRequest): Promise<IPermissionPoint[]> {
    const result: IPermissionPoint[] = []
    config.objectIDs.forEach((objectID) => {
      const rule = this._permissionMap.get(objectID)
      if (rule) {
        const item = {
          objectID,
          unitID: config.unitID,
          objectType: rule!.objectType,
          name: rule!.name,
          shareOn: false,
          shareRole: UnitRole.Owner,
          shareScope: -1,
          scope: {
            read: ObjectScope.AllCollaborator,
            edit: ObjectScope.AllCollaborator,
          },
          creator: createDefaultUser(UnitRole.Owner),
          strategies: [
            {
              action: UnitAction.View,
              role: UnitRole.Owner,
            },
            {
              action: UnitAction.Edit,
              role: UnitRole.Owner,
            },
          ],
          actions: config.actions.map((a) => {
            return { action: a, allowed: this._getRole(UnitRole.Owner) }
          }),
        }
        result.push(item)
      }
    })
    return result
  }

  async listCollaborators(): Promise<ICollaborator[]> {
    // List the existing collaborators
    return []
  }

  async allowed(_config: IAllowedRequest): Promise<IActionInfo[]> {
    // Because this is a mockService for handling permissions, we will not write real logic in it. We will only return an empty array to ensure that the permissions originally set by the user are not modified.
    // If you want to achieve persistence of permissions, you can modify the logic here.
    return Promise.resolve([])
  }

  async listRoles(): Promise<{ roles: IUnitRoleKV[]; actions: UnitAction[] }> {
    return {
      roles: [],
      actions: [],
    }
  }

  async update(config: IUpdatePermPointRequest): Promise<void> {
    // Update bit information
  }

  async updateCollaborator(): Promise<void> {
    // Update collaborator information
    return undefined
  }

  async createCollaborator(): Promise<void> {
    // Create new collaborator information
    return undefined
  }

  async deleteCollaborator(): Promise<void> {
    return undefined
  }

  async putCollaborators(config: IPutCollaboratorsRequest): Promise<void> {
    return undefined
  }
}

import { Plugin } from '@univerjs/core'

export class YourPlugin extends Plugin {
  static override pluginName = 'YOUR_AUTHZ_PLUGIN' // 添加静态pluginName属性

  constructor(
    _config: unknown,
    @Inject(Injector) protected override _injector: Injector,
  ) {
    super()
  }

  override onStarting(): void {
    this._injector.add([IAuthzIoService, { useClass: YourAuthzService }])
  }

  // Implement required abstract methods with empty bodies or default returns
  override onReady(): void {}
  override onRendered(): void {}
  override onSteady(): void {}
  getUnitType(): number {
    return 0
  }
  onDestroy(): void {}
  onCreated(): void {}
  onMounted(): void {}
  onUnMount(): void {}
  onUnLoad(): void {}
}

// 通过将 override 选项设置为 [[IAuthzIoService, null]]，可以告诉 Univer 不要注册内置的 IAuthzIoService。
// 这样，Univer 将使用你在 YourAuthzService 中提供的服务作为权限服务的实现。
// const univer = new Univer({
//   override: [[IAuthzIoService, null]],
// })

// univer.registerPlugin(YourPlugin)
